//
//  LYCommonBlock.h
//  LYAppMoudle
//
//  Created by 林域 on 2018/12/25.
//  Copyright © 2018 林域. All rights reserved.
//

#import <pthread.h>
#import <mach/mach_time.h>
#ifndef LYCommonBlock_h
#define LYCommonBlock_h
@import UIKit;

#pragma mark - Auto Fix Size -
static inline CGFloat LYAutoFixWidth(CGFloat length){
    CGFloat height = [UIScreen mainScreen].bounds.size.height;
    CGFloat width  = [UIScreen mainScreen].bounds.size.width;
    float a =  height < width ? height : width;
    return a / (375.0); // base on iphone 6;
}


#pragma mark - sand box -
// -- Sand Box -- //
#define LYSandBox_Document_BasePath NSHomeDirectory()
#define LYSandBox_Document_Path [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]
#define LYSandBox_Libarary_Path [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject]
#define LYSandBox_Cache_Path [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]
#define LYSandBox_Temp_Path NSTemporaryDirectory()


#pragma mark - screen -
//screen
#define LY_SCREEN_Scale  [UIScreen mainScreen].scale
#define LY_SCREEN_Size   [[UIScreen mainScreen] bounds].size
#define LY_SCREEN_Width  [[UIScreen mainScreen] bounds].width
#define LY_SCREEN_Height [[UIScreen mainScreen] bounds].height
#define LY_VIEW_Size     self.view.frame.size
#define LY_VIEW_Width    self.view.frame.size.width
#define LY_VIEW_Height   self.view.frame.size.height


#pragma mark - NSUserDefault -
//Userdefault
#define LYUserDefault [NSUserDefaults standardUserDefaults]

static inline void LYUserDefaultSetObjForKey(id obj, NSString *_Nonnull key){
    [LYUserDefault setObject:obj forKey:key];
    [LYUserDefault synchronize];
}
static inline id LYUserDefaultObjForKey(NSString *_Nonnull key){
    return [LYUserDefault objectForKey:key];
}

#pragma mark - System Info -

// system
#define LY_SYS_CurrentLanguage [[NSLocale preferredLanguages] firstObject]
#define LY_SYS_CpuCount [NSProcessInfo processInfo].activeProcessorCount


#pragma mark - App Info -
// app
#define LY_APP_Name    [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"]
#define LY_APP_Version [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]
#define LY_APP_BuildID [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]
#define LY_APP_Identifier [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"]


#pragma mark - singleton -
/* singleton **/
//.h
#define IMSingletonH(name) +(instancetype)shared##name;
//.m
#define IMSingletonM(name) \
static id _instance;\
+ (instancetype)allocWithZone:(struct _NSZone *)zone{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
return _instance;\
}\
+ (instancetype)shared##name{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [[self alloc] init];\
});\
return _instance;\
}\
- (id)copyWithZone:(NSZone *)zone{\
return _instance;\
}


#pragma mark - weak reference -
#ifndef weakify
#if DEBUG
#if __has_feature(objc_arc)
#define weakify(object) autoreleasepool{} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) autoreleasepool{} __block __typeof__(object) block##_##object = object;
#endif
#else
#if __has_feature(objc_arc)
#define weakify(object) try{} @finally{} {} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) try{} @finally{} {} __block __typeof__(object) block##_##object = object;
#endif
#endif
#endif

#ifndef strongify
#if DEBUG
#if __has_feature(objc_arc)
#define strongify(object) autoreleasepool{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) autoreleasepool{} __typeof__(object) object = block##_##object;
#endif
#else
#if __has_feature(objc_arc)
#define strongify(object) try{} @finally{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) try{} @finally{} __typeof__(object) object = block##_##object;
#endif
#endif
#endif


#pragma mark - Thread -
/**
 Submits a block for asynchronous execution on a main queue and returns immediately.
 */
static inline void dispatch_async_on_main_queue(void (^block)()){
    if (pthread_main_np()) {
        block();
    } else {
        dispatch_async(dispatch_get_main_queue(), block);
    }
}

/**
 Submits a block for execution on a main queue and waits until the block completes.
 */
static inline void dispatch_sync_on_main_queue(void (^block)()) {
    if (pthread_main_np()) {
        block();
    } else {
        dispatch_sync(dispatch_get_main_queue(), block);
    }
}



#pragma mark - 打印消息执行时间

#define LYAbsoluteTime CFAbsoluteTimeGetCurrent();

CGFloat BNRTimeBlock (void (^block)(void)) {
    mach_timebase_info_data_t info;
    if (mach_timebase_info(&info) != KERN_SUCCESS) return -1.0;
    
    uint64_t start = mach_absolute_time ();
    block ();
    uint64_t end = mach_absolute_time ();
    uint64_t elapsed = end - start;
    
    uint64_t nanos = elapsed * info.numer / info.denom;
    return (CGFloat)nanos / NSEC_PER_SEC;
    
} // BNRTimeBlock



#endif /* LYCommonBlock_h */
